home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE6 / PD / PDF / GuiLib / Task / c++ / GuiRegister < prev    next >
Text File  |  2003-02-14  |  25KB  |  770 lines

  1. //--------------------------------------------------------------------------
  2. //
  3. //   Copyright (c) 2002, Colin Granville
  4. //
  5. //   All rights reserved.
  6. //
  7. //   Redistribution and use in source and binary forms, with or
  8. //   without modification, are permitted provided that the following 
  9. //   conditions are met:
  10. //
  11. //      * Redistributions of source code must retain the above copyright 
  12. //        notice, this list of conditions and the following disclaimer.
  13. //
  14. //      * Redistributions in binary form must reproduce the above 
  15. //        copyright notice, this list of conditions and the following 
  16. //        disclaimer in the documentation and/or other materials 
  17. //        provided with the distribution.
  18. //
  19. //      * The name Colin Granville may not be used to endorse or promote 
  20. //        products derived from this software without specific prior 
  21. //        written permission.
  22. //
  23. //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  24. //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  25. //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  26. //   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  27. //   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  28. //   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  29. //   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  30. //   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  31. //   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  32. //   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  33. //   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
  34. //   OF THE POSSIBILITY OF SUCH DAMAGE.
  35. //
  36. //--------------------------------------------------------------------------
  37.  
  38. #include "GuiTargets.h"
  39. #include "GuiTask.h"
  40. #include "GuiToolbox.h"
  41. #include "GuiWindow.h"
  42. #include "ERROR.h"
  43. #include <stdlib.h>
  44.  
  45. GuiEventTarget::~GuiEventTarget() {}
  46.  
  47. inline unsigned int monotonic_time() {return _swi(OS_ReadMonotonicTime,_RETURN(0));}
  48.  
  49. class Initialise
  50. {
  51.   public:
  52.    Initialise();
  53.  
  54.   private:
  55.    GUI_DECLARE_EVENT_TARGETS(Initialise);
  56.  
  57.    Claim toolbox_error(GuiToolboxEvent &event,const GuiIdBlock&);
  58.    Claim quit_quit(GuiToolboxEvent &event,const GuiIdBlock&);
  59.    Claim default_redraw(GuiWimpPollBlock& blk,const GuiIdBlock&);
  60.    Claim default_key_press(GuiWimpPollBlock& blk,const GuiIdBlock&);
  61.    Claim quit_message(GuiWimpMessage&);
  62. };
  63.  
  64. Initialise::Initialise()
  65. {
  66.   new GuiToolboxTarget(0,GuiToolbox::Error::Event,this,Initialise::toolbox_error);
  67.   new GuiToolboxTarget(0,0x82a90+1,this,Initialise::quit_quit);
  68.   new GuiWimpTarget(0,GuiWimp_ERedrawWindow,this,Initialise::default_redraw);
  69.   new GuiWimpTarget(0,GuiWimp_EKeyPressed,this,Initialise::default_key_press);
  70.   new GuiMessageTarget(GuiWimp_MQuit,this,Initialise::quit_message);
  71. }
  72. //*********************************************************************
  73.  
  74. Claim Initialise::toolbox_error(GuiToolboxEvent &event,const GuiIdBlock&)
  75. {
  76.    GuiToolbox::Error* err=(GuiToolbox::Error*)&event;
  77.    WARN((_kernel_oserror*)&err->errnum);
  78.    return CLAIM;
  79. }
  80.  
  81. //*********************************************************************
  82.  
  83. Claim Initialise::quit_quit(GuiToolboxEvent&,const GuiIdBlock&)
  84. {
  85.    exit(0);
  86.    return CLAIM;
  87. }
  88.  
  89. //*********************************************************************
  90.  
  91. Claim Initialise::default_redraw(GuiWimpPollBlock& blk,const GuiIdBlock&)
  92. {
  93.    GuiRedrawWindowBlock& rb = (GuiRedrawWindowBlock&)blk;
  94.    int more=0;
  95.    GuiWindow::redraw(rb,more);
  96.    while (more) GuiWindow::getRectangle(rb,more);
  97.    return CLAIM;
  98. }
  99.  
  100. //*********************************************************************
  101.  
  102. Claim Initialise::default_key_press(GuiWimpPollBlock& blk,const GuiIdBlock&)
  103. {
  104.   _swi(Wimp_ProcessKey,_IN(0),blk.keyPressed.keyCode);
  105.   return CLAIM;
  106. }
  107.  
  108. //*********************************************************************
  109.  
  110. Claim Initialise::quit_message(GuiWimpMessage&)
  111. {
  112.   exit(0);
  113.   return CLAIM;
  114. }
  115. //********************************************************************************
  116.  
  117. GuiIdBlock* id_block;
  118.  
  119. void GuiRegister::initialise(GuiIdBlock& id_blk) 
  120. {
  121.   if (id_block!=0) return;
  122.   id_block=&id_blk;
  123.   new Initialise;
  124. }
  125.  
  126. //********************************************************************************
  127. //********************************************************************************
  128.  
  129. class GuiNullEventRegisterItem
  130. {
  131.   public:
  132.    GuiNullEventRegisterItem*          next;
  133.    GuiNullEventRegisterItem*          previous;
  134.    unsigned int                       interval;
  135.    unsigned int                       call_time;
  136.    GuiNullEventTarget*                command;
  137.    int                                thread_count;
  138.  
  139.    bool is_deleted()                        {return command==0;}
  140.    
  141.    bool match(unsigned int null_time)          {return !is_deleted() && call_time<=null_time;}
  142.    GuiNullEventRegisterItem* dispatch(GuiNullEventRegisterItem** first);
  143.    void  remove(GuiNullEventRegisterItem** first)
  144.          {
  145.          if (thread_count)
  146.             {
  147.             if (command) {command->item=0;command=0;}
  148.             }
  149.          else
  150.             {
  151.             if (command) command->item=0;
  152.             if (next) next->previous=previous;
  153.             if (previous) 
  154.                 previous->next=next;
  155.             else
  156.                 *first=next;
  157.             if (command) {command->item=0;command=0;}
  158.             delete this;
  159.             }
  160.          }
  161. };
  162.  
  163. //********************************************************************************
  164.  
  165. GuiNullEventRegisterItem* GuiNullEventRegisterItem::dispatch(GuiNullEventRegisterItem** first)
  166. {
  167.   thread_count++;
  168.   if (command) command->execute();
  169.   thread_count--;
  170.   GuiNullEventRegisterItem* next_item=next;
  171.   if (is_deleted() && thread_count==0) remove(first);
  172.   return next_item;
  173. }
  174.  
  175. //********************************************************************************
  176.  
  177. class GuiNullEventRegister
  178. {
  179.   public:
  180.     GuiNullEventRegister();
  181.     GuiNullEventRegisterItem* add(unsigned int interval,GuiNullEventTarget* command);
  182.     void                   remove(GuiNullEventRegisterItem*);
  183.     void                   dispatch();
  184.     unsigned int           get_null_event_time() const {return null_event_time;}
  185.     unsigned int           get_minimum_return_time() const {return minimum_return_time;}
  186.     void                   set_interval(GuiNullEventRegisterItem*,unsigned int interval);
  187.  
  188.     operator const void*() const {return first;}
  189.     operator void*()             {return first;}
  190.     bool operator!() const       {return first==0;}
  191.   private:
  192.     GuiNullEventRegisterItem* first;
  193.     unsigned int null_event_time;
  194.     unsigned int minimum_return_time;
  195. } null_event_register;
  196.  
  197. //********************************************************************************
  198.  
  199. GuiNullEventRegister::GuiNullEventRegister()
  200.  : first(0),
  201.    null_event_time(monotonic_time()),
  202.    minimum_return_time(null_event_time)
  203. {
  204. }
  205. //********************************************************************************
  206. void GuiNullEventRegister::dispatch()
  207. {
  208.   null_event_time=monotonic_time();
  209.   GuiNullEventRegisterItem* p=first;
  210.   GuiNullEventRegisterItem* next;
  211.   unsigned int min_time=0xffffffff;
  212.   minimum_return_time=min_time;
  213.   while (p)
  214.         {
  215.         if (!p->is_deleted())
  216.            {
  217.            if (p->call_time<=null_event_time)
  218.               {
  219.               next = p->dispatch(&first);
  220.               p->call_time=null_event_time+p->interval;
  221.               if (p->call_time<min_time) min_time=p->call_time;
  222.               p=next;
  223.               }
  224.            else 
  225.               {
  226.               if (p->call_time<min_time) min_time=p->call_time;
  227.               p=p->next;
  228.               }
  229.            }
  230.         else p=p->next;
  231.         }
  232.   if (min_time<minimum_return_time) minimum_return_time=min_time;
  233. }
  234.  
  235.  
  236. //********************************************************************************
  237.  
  238. GuiNullEventRegisterItem* GuiNullEventRegister::add(unsigned int interval,GuiNullEventTarget* command)
  239. {
  240.   GuiNullEventRegisterItem* p=new GuiNullEventRegisterItem;
  241.   if (p) 
  242.      {
  243.      p->interval=interval;
  244.      p->call_time=interval+null_event_time;
  245.      p->command=command;
  246.      p->thread_count=0;
  247.      if (p->call_time<minimum_return_time) minimum_return_time=p->call_time;
  248.      p->next=first;
  249.      p->previous=0;
  250.      if (p->next) p->next->previous=p;
  251.      first=p;
  252.      }
  253.   return p;
  254. }
  255.  
  256. //********************************************************************************
  257.  
  258. void GuiNullEventRegister::remove(GuiNullEventRegisterItem* item)
  259. {
  260.   if (item) item->remove(&first);
  261. }
  262.  
  263. //********************************************************************************
  264.  
  265. void  GuiNullEventRegister::set_interval(GuiNullEventRegisterItem* item,unsigned int interval)
  266. {
  267.   if (item)
  268.      {
  269.      item->interval=interval;
  270.      unsigned int call_time=null_event_time+interval;
  271.      if (call_time<minimum_return_time) minimum_return_time=call_time;
  272.      }
  273. }
  274. //********************************************************************************
  275. //********************************************************************************
  276.  
  277. GuiNullEventTarget::GuiNullEventTarget()
  278.  : item(0) {}
  279.  
  280. //********************************************************************************
  281.  
  282. GuiNullEventTarget::GuiNullEventTarget(unsigned int interval)
  283.  : item(0)
  284. {
  285.    setInterval(interval);
  286. }
  287. //********************************************************************************
  288.  
  289. GuiNullEventTarget::~GuiNullEventTarget() {destroy();}
  290.  
  291. //********************************************************************************
  292.  
  293. void GuiNullEventTarget::setInterval(unsigned int interval)
  294. {
  295.   if (item)
  296.      null_event_register.set_interval(item,interval);
  297.   else
  298.      item=null_event_register.add(interval,this);
  299. }
  300.  
  301. //********************************************************************************
  302.  
  303. void GuiNullEventTarget::destroy()
  304. {
  305.   if (item) null_event_register.remove(item);
  306. }
  307. //********************************************************************************
  308. //********************************************************************************
  309. //********************************************************************************
  310.  
  311. class GuiWimpRegisterItem
  312. {
  313.   public:
  314.    GuiWimpRegisterItem*          next;
  315.    GuiWimpRegisterItem*          previous;
  316.    GuiObjectId                   id;
  317.    int                           event_code;
  318.    GuiWimpEventTarget*           command;
  319.    int                           thread_count;
  320.  
  321.    bool is_deleted()                        {return command==0;}
  322.    bool match(const GuiIdBlock& id_block)   {return !is_deleted() &&
  323.                                                     (id_block.self.id==id || id==NULL_GuiObjectId);}
  324.    GuiWimpRegisterItem* dispatch(GuiWimpPollBlock& wpb,const GuiIdBlock& id_block,GuiWimpRegisterItem** first);
  325.    void  remove(GuiWimpRegisterItem** first)
  326.          {
  327.          if (thread_count)
  328.             {
  329.             if (command) {command->item=0;command=0;}
  330.             }
  331.          else
  332.             {
  333.             if (next) next->previous=previous;
  334.             if (previous) 
  335.                 previous->next=next;
  336.             else
  337.                 *first=next;
  338.             delete this;
  339.             if (command) {command->item=0;command=0;}
  340.             }
  341.          }
  342. };
  343.  
  344. //********************************************************************************
  345.  
  346. GuiWimpRegisterItem* GuiWimpRegisterItem::dispatch(GuiWimpPollBlock& wpb,const GuiIdBlock& id_block,
  347.                                                    GuiWimpRegisterItem** first)
  348. {
  349.   thread_count++;
  350.   Claim claim=(is_deleted())?DONT_CLAIM:command->execute(wpb,id_block);
  351.   thread_count--;
  352.   GuiWimpRegisterItem* next_item=next;
  353.   if (is_deleted() && thread_count==0) remove(first);
  354.   return (claim==DONT_CLAIM)?next_item:0;
  355. }
  356.  
  357. //********************************************************************************
  358.  
  359. class GuiWimpRegister
  360. {
  361.   public:
  362.     GuiWimpRegisterItem* add(int event_code,GuiObjectId,GuiWimpEventTarget*);
  363.     void remove(GuiWimpRegisterItem*);
  364.     void dispatch(int event_code,GuiWimpPollBlock& wpb,const GuiIdBlock& id_block);
  365.  
  366.   private:
  367.     GuiWimpRegisterItem* event_list[32];
  368. }wimp_register;
  369.  
  370. //********************************************************************************
  371. void GuiWimpRegister::dispatch(int event_code,GuiWimpPollBlock& wpb,const GuiIdBlock& id_block)
  372. {
  373.   if (event_code>=32) return;
  374.   GuiWimpRegisterItem** first=&event_list[event_code];
  375.   GuiWimpRegisterItem* p=*first;
  376.   while (p)
  377.         {
  378.         if (p->match(id_block))
  379.             p = p->dispatch(wpb,id_block,first);
  380.         else p=p->next;
  381.         }
  382. }
  383.  
  384.  
  385. //********************************************************************************
  386.  
  387. GuiWimpRegisterItem* GuiWimpRegister::add(int event_code,GuiObjectId id,GuiWimpEventTarget* command)
  388. {
  389.   if (event_code>=32) return 0;
  390.   GuiWimpRegisterItem* p=new GuiWimpRegisterItem;
  391.   if (p) 
  392.      {
  393.      p->id=id;
  394.      p->event_code=event_code;
  395.      p->command=command;
  396.      p->thread_count=0;
  397.  
  398.      p->next=event_list[event_code];;
  399.      p->previous=0;
  400.      if (p->next) p->next->previous=p;
  401.      event_list[event_code]=p;
  402.      }
  403.   return p;
  404. }
  405.  
  406. //********************************************************************************
  407.  
  408. void GuiWimpRegister::remove(GuiWimpRegisterItem* item)
  409. {
  410.   if (item) item->remove(&event_list[item->event_code]);
  411. }
  412.  
  413. //********************************************************************************
  414. //********************************************************************************
  415.  
  416. GuiWimpEventTarget::GuiWimpEventTarget() : item(0) {}
  417.  
  418. GuiWimpEventTarget::GuiWimpEventTarget(const GuiObject* obj, int event_code)
  419.  : item(0)
  420. {
  421.    setListener(obj,event_code);
  422. }
  423. //********************************************************************************
  424.  
  425. GuiWimpEventTarget::~GuiWimpEventTarget() {destroy();}
  426.  
  427. //********************************************************************************
  428.  
  429. void GuiWimpEventTarget::setListener(const GuiObject* object, int event_code)
  430. {
  431.   if (item) destroy();
  432.   GuiObjectId object_id =(object)?object->id():NULL_GuiObjectId;
  433.   item=wimp_register.add(event_code,object_id,this);
  434. }
  435. //********************************************************************************
  436.  
  437. void GuiWimpEventTarget::destroy()
  438. {
  439.   if (item) wimp_register.remove(item);
  440. }
  441. //********************************************************************************
  442. //********************************************************************************
  443.  
  444. class GuiToolboxRegisterItem
  445. {
  446.   public:
  447.    GuiToolboxRegisterItem*       next;
  448.    GuiToolboxRegisterItem*       previous;
  449.    int                           event_code;
  450.    GuiObjectId                   id;
  451.    GuiToolboxEventTarget*        command;
  452.    int                           thread_count;
  453.  
  454.    bool is_deleted()                {return command==0;}
  455.    bool match(int event_code,const GuiIdBlock& id_block)
  456.                {return !is_deleted() &&
  457.                        event_code==GuiToolboxRegisterItem::event_code && 
  458.                        (id_block.self.id==id || id_block.ancestor.id==id || id==NULL_GuiObjectId);}
  459.  
  460.    GuiToolboxRegisterItem* dispatch(GuiToolboxEvent& tbe,const GuiIdBlock& id_block,
  461.                                     GuiToolboxRegisterItem** first);
  462.    void  remove(GuiToolboxRegisterItem** first)
  463.          {
  464.          if (thread_count)
  465.             {
  466.             if (command) {command->item=0;command=0;}
  467.             }
  468.          else
  469.             {
  470.             if (next) next->previous=previous;
  471.             if (previous) 
  472.                 previous->next=next;
  473.             else
  474.                 *first=next;
  475.             if (command) {command->item=0;command=0;}
  476.             delete this;
  477.             }
  478.          }
  479. };
  480.  
  481. //********************************************************************************
  482.  
  483. GuiToolboxRegisterItem* GuiToolboxRegisterItem::dispatch(GuiToolboxEvent& tbe,
  484.                                               const GuiIdBlock& id_block,GuiToolboxRegisterItem** first)
  485. {
  486.   thread_count++;
  487.   Claim claim=(is_deleted())?DONT_CLAIM:command->execute(tbe,id_block);
  488.   thread_count--;
  489.   GuiToolboxRegisterItem* next_item=next;
  490.   if (is_deleted() && thread_count==0) remove(first);
  491.   return (claim==DONT_CLAIM)?next_item:0;
  492. }
  493.  
  494. //********************************************************************************
  495.  
  496. class GuiToolboxRegister
  497. {
  498.   public:
  499.     GuiToolboxRegisterItem* add(int event_code,GuiObjectId,GuiToolboxEventTarget*);
  500.     void remove(GuiToolboxRegisterItem*);
  501.     void dispatch(GuiToolboxEvent& tbe, const GuiIdBlock& id_block);
  502.  
  503.   private:
  504.     unsigned int hash(unsigned int event) {return (event & 0xf) | ((event & 0xf00)>>4);}
  505.     GuiToolboxRegisterItem* event_list[256];
  506. }toolbox_register;
  507.  
  508. //********************************************************************************
  509.  
  510.  
  511. void GuiToolboxRegister::dispatch(GuiToolboxEvent& tbe, const GuiIdBlock& id_block)
  512. {
  513.   GuiToolboxRegisterItem** first=&event_list[hash(tbe.eventCode)];
  514.   GuiToolboxRegisterItem* p=*first;
  515.   while (p)
  516.         {
  517.         if (p->match(tbe.eventCode,id_block))
  518.            p = p->dispatch(tbe,id_block,first);
  519.         else 
  520.            p=p->next;
  521.         }
  522. }
  523.  
  524. //********************************************************************************
  525.  
  526. GuiToolboxRegisterItem* GuiToolboxRegister::add(int event_code,GuiObjectId id,
  527.                                                 GuiToolboxEventTarget* command)
  528. {
  529.   GuiToolboxRegisterItem* p=new GuiToolboxRegisterItem;
  530.   if (p)
  531.      {
  532.      p->event_code=event_code;
  533.      p->id=id;
  534.      p->command=command;
  535.      p->thread_count=0;
  536.      unsigned int i=hash(event_code);
  537.      p->next=event_list[i];
  538.      p->previous=0;
  539.      if (p->next) p->next->previous=p;
  540.      event_list[i]=p;
  541.      }
  542.    return p;
  543. }
  544.  
  545. //********************************************************************************
  546.  
  547. void GuiToolboxRegister::remove(GuiToolboxRegisterItem* item)
  548.   if (item) item->remove(&event_list[hash(item->event_code)]);
  549. }
  550.  
  551. //********************************************************************************
  552. //********************************************************************************
  553.  
  554. GuiToolboxEventTarget::GuiToolboxEventTarget() : item(0) {}
  555.  
  556. GuiToolboxEventTarget::GuiToolboxEventTarget(const GuiObject* obj, int event_code)
  557.  : item(0)
  558. {
  559.    setListener(obj,event_code);
  560. }
  561. //********************************************************************************
  562.  
  563. GuiToolboxEventTarget::~GuiToolboxEventTarget() {destroy();}
  564.  
  565. //********************************************************************************
  566.  
  567. void GuiToolboxEventTarget::setListener(const GuiObject* object, int event_code)
  568. {
  569.   if (item) destroy();
  570.   GuiObjectId object_id =(object)?object->id():NULL_GuiObjectId;
  571.   item=toolbox_register.add(event_code,object_id,this);
  572. }
  573. //********************************************************************************
  574.  
  575. void GuiToolboxEventTarget::destroy()
  576. {
  577.   if (item) toolbox_register.remove(item);
  578. }
  579.  
  580. //********************************************************************************
  581. //********************************************************************************
  582. //********************************************************************************
  583.  
  584. class GuiMessageRegisterItem
  585. {
  586.   public:
  587.    GuiMessageRegisterItem*      next;
  588.    GuiMessageRegisterItem*      previous;
  589.    int                          message_code;
  590.    GuiMessageEventTarget*       command;
  591.    int                          thread_count;
  592.  
  593.    bool is_deleted()                {return command==0;}
  594.  
  595.    bool match(int message)          {return !is_deleted() && message==message_code;}
  596.    GuiMessageRegisterItem* dispatch(GuiWimpMessage& wm,GuiMessageRegisterItem** first);
  597.    void  remove(GuiMessageRegisterItem** first)
  598.          {
  599.          if (thread_count)
  600.             {
  601.             if (command) {command->item=0;command=0;}
  602.             }
  603.          else
  604.             {
  605.             if (next) next->previous=previous;
  606.             if (previous) 
  607.                 previous->next=next;
  608.             else
  609.                 *first=next;
  610.             if (command) {command->item=0;command=0;}
  611.             delete this;
  612.             }
  613.          }
  614.  
  615. };
  616.  
  617. //********************************************************************************
  618.  
  619. GuiMessageRegisterItem* GuiMessageRegisterItem::dispatch(GuiWimpMessage& wm,
  620.                                                          GuiMessageRegisterItem** first)
  621. {
  622.   thread_count++;
  623.   Claim claim=(is_deleted())?DONT_CLAIM:command->execute(wm);
  624.   thread_count--;
  625.   GuiMessageRegisterItem* next_item=next;
  626.   if (is_deleted() && thread_count==0) remove(first);
  627.   return (claim==DONT_CLAIM)?next_item:0;
  628. }
  629.  
  630. //********************************************************************************
  631.  
  632. class GuiMessageRegister
  633. {
  634.   public:
  635.     GuiMessageRegisterItem* add(int message_code,GuiMessageEventTarget*);
  636.     void remove(GuiMessageRegisterItem*);
  637.     void dispatch(GuiWimpMessage& wm);
  638.  
  639.   private:
  640.     unsigned int hash(int message_code) {return (message_code & 7) | ((message_code & 0x7c0)>>3);}
  641.     GuiMessageRegisterItem* event_list[256];
  642. }message_register;
  643.  
  644. //********************************************************************************
  645.  
  646. void GuiMessageRegister::dispatch(GuiWimpMessage& wm)
  647. {
  648.   GuiMessageRegisterItem** first=&event_list[hash(wm.hdr.actionCode)];
  649.   GuiMessageRegisterItem* p=*first;
  650.   while (p)
  651.         {
  652.         if (p->match(wm.hdr.actionCode))
  653.            p=p->dispatch(wm,first);
  654.         else p=p->next;
  655.         }
  656. }
  657.  
  658. //********************************************************************************
  659.  
  660. GuiMessageRegisterItem* GuiMessageRegister::add(int message_code,GuiMessageEventTarget* command)
  661. {
  662.   GuiMessageRegisterItem* p=new GuiMessageRegisterItem;
  663.   if (p)
  664.      {
  665.      p->message_code=message_code;
  666.      p->command=command;
  667.      p->thread_count=0;
  668.      unsigned int i=hash(message_code);
  669.      p->next=event_list[i];
  670.      p->previous=0;
  671.      if (p->next) p->next->previous=p;
  672.      event_list[i]=p;
  673.      }
  674.   return p;
  675. }
  676.  
  677. //********************************************************************************
  678.  
  679. void GuiMessageRegister::remove(GuiMessageRegisterItem* item)
  680. {
  681.   if (item) item->remove(&event_list[hash(item->message_code)]);
  682. }
  683.  
  684. //********************************************************************************
  685. //********************************************************************************
  686.  
  687. GuiMessageEventTarget::GuiMessageEventTarget() : item(0) {}
  688.  
  689. GuiMessageEventTarget::GuiMessageEventTarget(int message_code)
  690.  : item(0)
  691. {
  692.    setListener(message_code);
  693. }
  694. //********************************************************************************
  695.  
  696. GuiMessageEventTarget::~GuiMessageEventTarget() {destroy();}
  697.  
  698. //********************************************************************************
  699.  
  700. void GuiMessageEventTarget::setListener(int message_code)
  701. {
  702.   if (item) destroy();
  703.   item=message_register.add(message_code,this);
  704. }
  705. //********************************************************************************
  706.  
  707. void GuiMessageEventTarget::destroy()
  708. {
  709.   if (item) message_register.remove(item);
  710. }
  711.  
  712. //********************************************************************************
  713. //********************************************************************************
  714. //********************************************************************************
  715.  
  716. int               mask;
  717.  
  718. void GuiRegister::dispatch(int event_code,GuiWimpPollBlock& poll_block)
  719. {
  720.   if (id_block==0) return;
  721.   if (event_code<32)
  722.      {
  723.      switch (event_code)
  724.             {
  725.             case GuiWimp_ENull: null_event_register.dispatch();
  726.                                 break;
  727.             case 17:
  728.             case 18: message_register.dispatch(*(GuiWimpMessage*)&poll_block);
  729.                      return;
  730.             }
  731.      wimp_register.dispatch(event_code,poll_block,*id_block);
  732.      }
  733.   else if (event_code==0x200) 
  734.           toolbox_register.dispatch(*(GuiToolboxEvent*)&poll_block,*id_block);
  735. }
  736.  
  737.  
  738. //********************************************************************************
  739.  
  740. void GuiRegister::poll(int *ev_code, GuiWimpPollBlock* poll_blk, int* poll_w)
  741. {
  742.   static GuiWimpPollBlock _poll_block;
  743.   int                  _event_code;
  744.  
  745.   GuiWimpPollBlock* poll_block=(poll_blk)?poll_blk:&_poll_block;
  746.   int* event_code=(ev_code)?ev_code:&_event_code;
  747.  
  748.   if (!null_event_register)
  749.      {
  750.      _swix(Wimp_Poll,_INR(0,1) | _IN(3) | _OUT(0),mask | 1,poll_block,poll_w,event_code);
  751.      }     
  752.   else if (null_event_register.get_minimum_return_time()<=
  753.            null_event_register.get_null_event_time())
  754.           {
  755.           _swix(Wimp_Poll,_INR(0,1) | _IN(3) | _OUT(0),mask &~ 1,poll_block,poll_w,event_code);
  756.           }
  757.   else _swix(Wimp_PollIdle,_INR(0,3) | _OUT(0), mask &~ 1,poll_block,
  758.                      null_event_register.get_minimum_return_time(),poll_w,event_code);
  759.  
  760.    dispatch(*event_code,*poll_block);
  761. }
  762.  
  763. //********************************************************************************
  764.  
  765. unsigned int GuiRegister::get_null_event_time()
  766. {
  767.   return null_event_register.get_null_event_time();
  768. }
  769.